package ServerConnection;

import Client.ServerInfo;
import Message.AccountSendMessageInfo;
import utils.AccountSendMessageInfoFromOneList;
import utils.AccountSendMessageInfoList;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashSet;


/**
 * 该类为处理客户端轮询聊天记录的类，该类会返回AccountSendMessageInfoList给客户端，
 * 其每个节点是AccountSendMessageInfoFromOneList，即来自同一个人的所有消息
 * 而AccountSendMessageInfoFromOneList的每个节点即是每条消息，即AccountSendMessageInfo类
 * */
public class ReturnAccountSendMessageInfoServer implements Runnable{
    DatabaseServer databaseServer;

    ReturnAccountSendMessageInfoServer(DatabaseServer databaseServer) {
        this.databaseServer = databaseServer;
    }

    @Override
    public void run() {
        try {
            ServerSocket serverSocket = new ServerSocket(ServerInfo.SERVER_SENDREQUESTSREGULARLYTOGETMESSAGE_PORT);
            System.out.println("返回消息服务成功启动！");
            Socket socket;
            while (true) {
                socket = serverSocket.accept();
                Thread handle = new Thread(new ThreadHandleReturnAccountSendMessageInfo(socket, databaseServer));
                handle.start();
            }
        } catch (IOException e) {
            System.out.println("WARNING:ResponseFriendRequestServer Init fail,Reason:socket has ioException.");
        }
    }
}
/**
 * 该类为处理客户端轮询消息的线程类，该类会返回AccountSendMessageInfoList给客户端，
 * 其每个节点是AccountSendMessageInfoFromOneList，即来自同一个人的所有消息
 * 而AccountSendMessageInfoFromOneList的每个节点即是每条消息，即AccountSendMessageInfo类
 * */
 class ThreadHandleReturnAccountSendMessageInfo implements Runnable{
    Socket socket = null;
    DatabaseServer databaseServer;

    public ThreadHandleReturnAccountSendMessageInfo(Socket socket, DatabaseServer databaseServer) {
        super();
        this.socket = socket;
        this.databaseServer = databaseServer;
    }

    @Override
    public void run() {
        try {
            System.out.println("收到用户获取消息的请求，正在处理");
            //获取从客户端得到的消息，并且执行了消息。
            InputStream inputStream = socket.getInputStream();
            InputStreamReader inputStreamReader=new InputStreamReader(inputStream);//包装成字符流，提高效率
            BufferedReader bufferedReader=new BufferedReader(inputStreamReader);//缓冲区
            String userId = bufferedReader.readLine();//获得用户id
/*
            String sqlToGetUserFrom = String.format("SELECT userIdInDatabaseFrom,count(*) AS someOneHaveSendMessageNumber " +
                    "FROM Message WHERE `userIdInDatabaseTo`='%s'" + "AND Response=0 GROUP BY userIdInDatabaseFrom;", userId);*/
            String sqlToGetUserFrom = String.format("SELECT userIdInDatabaseFrom,count(*) AS someOneHaveSendMessageNumber " +
                    "FROM Message WHERE `userIdInDatabaseTo`='%s'"
                    + " GROUP BY userIdInDatabaseFrom;", userId);

            ResultSet userFrom = databaseServer.returnResultSet(sqlToGetUserFrom);

            ArrayList<String> userIdInDatabaseFromArray = new ArrayList<>();
            int numberOfHaveSendedMessageUser = 0;
            while (userFrom.next()) {
                numberOfHaveSendedMessageUser++;
                userIdInDatabaseFromArray.add(userFrom.getString("userIdInDatabaseFrom"));
            }
            System.out.println("numberOfHaveSendedMessageUser:"+numberOfHaveSendedMessageUser);

            AccountSendMessageInfoList accountSendMessageInfoList = new AccountSendMessageInfoList();
            ArrayList<Integer> AccountSendMessageInfoIdArrayList = new ArrayList<>();/**用来存储已经被转发的AccountSendMessageInfo 的id，以在后面设置其response为1*/
            if (numberOfHaveSendedMessageUser == 0) {
                System.out.println("该用户离线期间没有人给他发送消息");
            }else {
                for (int i = 0; i < numberOfHaveSendedMessageUser; i++) {
                    /*String allMessagesSentByOnePersonSQL = "SELECT * FROM Message WHERE userIdInDatabaseTo='" +
                            userId + "' AND userIdInDatabaseFrom = '" + userIdInDatabaseFromArray.get(i)
                            + "' And `Response`=0 order by time;";
                    */

                    String allMessagesSentByOnePersonSQL = "SELECT * FROM Message WHERE (userIdInDatabaseTo='" +
                            userId + "' AND userIdInDatabaseFrom = '" + userIdInDatabaseFromArray.get(i)
                            + "') or (userIdInDatabaseTo='" + userIdInDatabaseFromArray.get(i) +
                            "' AND userIdInDatabaseFrom = '" + userId + " ') order by time;";

                    System.out.println("sql: "+ allMessagesSentByOnePersonSQL);
                    ResultSet allmessageSentByOnePerson = databaseServer.returnResultSet(allMessagesSentByOnePersonSQL);
                    AccountSendMessageInfoFromOneList accountSendMessageInfoFromOneList = new AccountSendMessageInfoFromOneList();
                    while (allmessageSentByOnePerson.next()) {
                        String userIdInDatabaseFrom = allmessageSentByOnePerson.getString("userIdInDatabaseFrom");
                        String userIdInDatabaseTo = allmessageSentByOnePerson.getString("userIdInDatabaseTo");
                        String messageInfo = allmessageSentByOnePerson.getString("message");
                        Timestamp timestamp = allmessageSentByOnePerson.getTimestamp("time");
                        AccountSendMessageInfo accountSendMessageInfo = new AccountSendMessageInfo(userIdInDatabaseFrom, userIdInDatabaseTo, messageInfo, timestamp);
                        accountSendMessageInfoFromOneList.add(accountSendMessageInfo);
                        AccountSendMessageInfoIdArrayList.add(Integer.valueOf(allmessageSentByOnePerson.getInt("MessageId")));
                        //System.out.println("accountSendMessageInfo:"+accountSendMessageInfo.getInfo());
                    }
                    accountSendMessageInfoList.add(accountSendMessageInfoFromOneList);
                }
            }

            String sqlToGetUserTo = String.format("SELECT userIdInDatabaseTo,count(*) AS someOneHaveSendMessageNumber " +
                    "FROM Message WHERE `userIdInDatabaseFrom`='%s'"
                    + " GROUP BY userIdInDatabaseTo;", userId);
            ResultSet userTo = databaseServer.returnResultSet(sqlToGetUserTo);
            ArrayList<String> userIdInDatabaseToArray = new ArrayList<>();
            while (userTo.next()) {
                userIdInDatabaseToArray.add(userTo.getString("userIdInDatabaseTo"));
            }
            HashSet hs1 = new HashSet(userIdInDatabaseFromArray);
            HashSet hs2 = new HashSet(userIdInDatabaseToArray);
            hs2.removeAll(hs1);
            ArrayList<String> finalUserIdInDatabaseToArray = new ArrayList<>();
            finalUserIdInDatabaseToArray.addAll(hs2);
            int numberOfHaveSendedToUser = finalUserIdInDatabaseToArray.size();
            if (numberOfHaveSendedToUser == 0) {
                System.out.println("用户没有给（没有发送消息给他的用户）发送消息");
            }else {
                for (int i = 0; i < numberOfHaveSendedToUser; i++) {
                    String allMessagesSentByOnePersonSQL = "SELECT * FROM Message WHERE (userIdInDatabaseFrom='" +
                            userId + "' AND userIdInDatabaseTo = '" + finalUserIdInDatabaseToArray.get(i)
                            + " ') order by time;";

                    System.out.println("sql: "+ allMessagesSentByOnePersonSQL);
                    ResultSet allmessageSentByOnePerson = databaseServer.returnResultSet(allMessagesSentByOnePersonSQL);
                    AccountSendMessageInfoFromOneList accountSendMessageInfoFromOneList = new AccountSendMessageInfoFromOneList();
                    while (allmessageSentByOnePerson.next()) {
                        String userIdInDatabaseFrom = allmessageSentByOnePerson.getString("userIdInDatabaseFrom");
                        String userIdInDatabaseTo = allmessageSentByOnePerson.getString("userIdInDatabaseTo");
                        String messageInfo = allmessageSentByOnePerson.getString("message");
                        Timestamp timestamp = allmessageSentByOnePerson.getTimestamp("time");
                        AccountSendMessageInfo accountSendMessageInfo = new AccountSendMessageInfo(userIdInDatabaseFrom, userIdInDatabaseTo, messageInfo, timestamp);
                        accountSendMessageInfoFromOneList.add(accountSendMessageInfo);
                        AccountSendMessageInfoIdArrayList.add(Integer.valueOf(allmessageSentByOnePerson.getInt("MessageId")));
                        //System.out.println("accountSendMessageInfo:"+accountSendMessageInfo.getInfo());
                    }
                    accountSendMessageInfoList.add(accountSendMessageInfoFromOneList);
                }
            }



            Boolean result = databaseServer.bulkUpdateMessageResponse(AccountSendMessageInfoIdArrayList);
            System.out.println("批量更新message.response=1 "+result);
            //返还执行的结果到客户端。
            OutputStream outputStream = socket.getOutputStream(); //获取一个输出流，向服务端发送信息
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
            objectOutputStream.writeObject(accountSendMessageInfoList);

            //inputStream.close();
            //objectOutputStream.close();
            //outputStream.close();
            //socket.close();


        } catch (IOException | SQLException e) {
            e.printStackTrace();
        }
    }
}